package com.kiven.ui

import com.google.gson.*
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.showOkCancelDialog
import com.intellij.ui.DocumentAdapter
import com.intellij.ui.components.*
import com.intellij.ui.dsl.builder.Cell
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.layout.CellBuilder
import com.intellij.util.ui.JBDimension
import com.intellij.util.ui.JBEmptyBorder
import com.ruiyu.jsontodart.CollectInfo
import com.ruiyu.setting.Settings
import com.ruiyu.ui.LineNumberHeaderView
import com.ruiyu.ui.myInputValidator
import com.ruiyu.utils.addComponentIntoVerticalBoxAlignmentLeft
import java.awt.BorderLayout
import java.awt.event.ActionEvent
import javax.swing.*
import javax.swing.event.DocumentEvent
import javax.swing.text.JTextComponent


open class JsonInputDialogK(
    project: Project,
    val inputModelBlock: (inputModel: CollectInfo) -> Boolean
) : Messages.InputDialog(
    project,
    "请输入类名和JSON字符串以生成dart bean类",
    "生成Dart bean类代码",
    Messages.getInformationIcon(),
    "",
    myInputValidator
) {

    private lateinit var classNameInput: JTextField

    private val prettyGson: Gson = GsonBuilder().setPrettyPrinting().serializeNulls().create()

    init {
        setOKButtonText("确定")
    }

    override fun createMessagePanel(): JPanel {
        val messagePanel = JPanel(BorderLayout())
        if (myMessage != null) {
            val textComponent = createTextComponent()
            messagePanel.add(textComponent, BorderLayout.NORTH)
        }
        myField = createTextFieldComponent()


//        val classNameInputContainer = createLinearLayout()

        val classNameRow = createLinearLayout(true)
        classNameRow.border = JBEmptyBorder(5, 0, 5, 0)
        classNameRow.preferredSize = JBDimension(500, 40)

        val classNameTitle = JBLabel("类名: ")

        classNameInput = JBTextField()
        classNameInput.preferredSize = JBDimension(100, 40)
        myInputValidator.classNameField = classNameInput

        classNameInput.document.addDocumentListener(object : DocumentAdapter() {
            override fun textChanged(e: DocumentEvent) {
                okAction.isEnabled = myInputValidator.checkInput(myField.text)
            }
        })

        classNameRow.add(classNameTitle)
        classNameRow.add(classNameInput)
        classNameRow.add(JBLabel("后缀: ").apply { border = JBEmptyBorder(0, 10, 0, 0) })
        classNameRow.add(JBTextField())


        val createScrollableTextComponent = createMyScrollableTextComponent()
        val jsonInputContainer = createLinearLayout()
        jsonInputContainer.preferredSize = JBDimension(700, 400)
        jsonInputContainer.border = JBEmptyBorder(5, 0, 5, 5)
        val jsonTitle = JBLabel("JSON:")
        jsonTitle.border = JBEmptyBorder(5, 0, 5, 0)
        jsonInputContainer.addComponentIntoVerticalBoxAlignmentLeft(jsonTitle)
        jsonInputContainer.addComponentIntoVerticalBoxAlignmentLeft(createScrollableTextComponent)


        val centerContainer = JPanel()
        val centerBoxLayout = BoxLayout(centerContainer, BoxLayout.PAGE_AXIS)
        centerContainer.layout = centerBoxLayout
        centerContainer.addComponentIntoVerticalBoxAlignmentLeft(classNameRow)
        centerContainer.addComponentIntoVerticalBoxAlignmentLeft(jsonInputContainer)
        messagePanel.add(centerContainer, BorderLayout.CENTER)
        val formatButton = JButton("检测格式")
        formatButton.horizontalAlignment = SwingConstants.CENTER
        formatButton.addActionListener(object : AbstractAction() {
            override fun actionPerformed(p0: ActionEvent?) {
                handleFormatJSONString()
            }

        })
        val settingContainer = JPanel()
        settingContainer.border = JBEmptyBorder(0, 5, 5, 7)
        val boxLayout = BoxLayout(settingContainer, BoxLayout.LINE_AXIS)
        settingContainer.layout = boxLayout
        /// 原有界面代码配置错误修改
//        settingContainer.add(Box.createHorizontalGlue())
//        settingContainer.add(formatButton)
//        messagePanel.add(settingContainer, BorderLayout.SOUTH)
//        messagePanel.add(createCheckBox(), BorderLayout.SOUTH)
        settingContainer.add(createCheckBox())
        settingContainer.add(Box.createHorizontalGlue())
        settingContainer.add(formatButton)
        messagePanel.add(settingContainer, BorderLayout.SOUTH)

        return messagePanel
    }
    private fun createLinearLayout(isRow: Boolean = false): JPanel {
        val container = JPanel()
        val boxLayout = BoxLayout(container, if (isRow) BoxLayout.LINE_AXIS else BoxLayout.PAGE_AXIS)
        container.layout = boxLayout
        return container
    }

    override fun createTextFieldComponent(): JTextComponent {
        val jTextArea = JTextArea(15, 50)
        jTextArea.minimumSize = JBDimension(750, 400)
//        jTextArea.lineWrap = true
//        jTextArea.wrapStyleWord = true
//        jTextArea.autoscrolls = true
        return jTextArea
    }


    private fun createMyScrollableTextComponent(): JComponent {
        val jbScrollPane = JBScrollPane(myField)
        jbScrollPane.preferredSize = JBDimension(700, 350)
        jbScrollPane.autoscrolls = true
        jbScrollPane.horizontalScrollBarPolicy = JBScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
        jbScrollPane.verticalScrollBarPolicy = JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED

        jbScrollPane.setRowHeaderView(LineNumberHeaderView())

        return jbScrollPane
    }


    override fun getPreferredFocusedComponent(): JComponent? {
        return if (classNameInput.text?.isEmpty() == false) {
            myField
        } else {
            classNameInput
        }
    }

    fun handleFormatJSONString() {
        val currentText = myField.text ?: ""
        if (currentText.isNotEmpty()) {
            try {
                val jsonElement = prettyGson.fromJson<JsonElement>(currentText, JsonElement::class.java)
                val formatJSON = prettyGson.toJson(jsonElement)
                myField.text = formatJSON
            } catch (e: Exception) {
                showOkCancelDialog("error(按Esc键可关闭)", e.localizedMessage + "\n${e.message}" + "\n\n实际的错误行数可能比提示的行数少一行或多行", "确定")
            }
        }

        feedBackFormatJSONActionInfo()

    }

    private fun feedBackFormatJSONActionInfo() {
//        Thread { sendActionInfo(prettyGson.toJson(FormatJSONAction())) }.start()
    }

    override fun doOKAction() {

        val collectInfo = CollectInfo().apply {
            userInputClassName = classNameInput.text
            userInputJson = myField.text
        }
        if (collectInfo.userInputClassName.isEmpty()) {
            throw Exception("className must not null or empty")
        }
        if (collectInfo.userInputJson.isEmpty()) {
            throw Exception("json must not null or empty")
        }

        if (inputModelBlock(collectInfo)) {
            super.doOKAction()
        }
    }

    private fun createCheckBox(): DialogPanel {
        val isOpenNullSafety = Settings.instance().isOpenNullSafety == true
        var naCB: Cell<JBCheckBox>? = null
        return panel {
            row {
                checkBox("null-safety").apply {
                    component.isSelected = isOpenNullSafety
                    component.addItemListener {
                        naCB?.component?.isVisible = component.isSelected
                        Settings.instance().isOpenNullSafety = component.isSelected
                    }
                }

                checkBox(
                    "null-able",
                ).apply {
                    naCB = this

                    component.isSelected = isOpenNullSafety && Settings.instance().isOpenNullAble == true
                    component.isVisible = isOpenNullSafety
                    component.addItemListener {
                        Settings.instance().isOpenNullAble = component.isSelected
                    }
                }
            }
        }
    }
}
